using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using System.Text;
using System.Transactions;
using System.Xml;
using Common.Utilities;
using Common.Utilities.Dispatcher;

namespace Workflows.Components.DALC
{
    /// <summary></summary>
    public class RunDALC
    {
        /// <summary></summary>
        public static void SaveRun(Run run)
        {
            string connStr = ConfigurationManager.ConnectionStrings["Workflow"].ConnectionString;
            SqlConnection conn=new SqlConnection(connStr);
            TransactionScope scope = new TransactionScope();
            try
            {
                conn.Open();
                SqlCommand cmd = conn.CreateCommand();
                cmd.CommandText = "SaveRun";
                cmd.CommandType = CommandType.StoredProcedure;
                SqlParameter runIDparam=new SqlParameter("@RunID",run.RunID.ToString());
                SqlParameter workflowIDParam=new SqlParameter("@WorkflowID",run.WorkflowID.ToString());
                SqlParameter triggerInstanceIDParam=new SqlParameter("@TriggerInstanceID",run.TriggerInstanceID.ToString());
                SqlParameter submitTimeParam=new SqlParameter("@SubmitTime",run.SubmitTime);
                SqlParameter startTimeParam=new SqlParameter("@StartTime",run.StartTime);
                SqlParameter finishTimeParam=new SqlParameter("@FinishTime",run.FinishTime);
                XmlDocument xDoc =new XmlDocument();
                xDoc.LoadXml("<GlobalVariables></GlobalVariables>");
                XmlNode varRootNode = xDoc.DocumentElement;
                if(run.Vars !=null && run.Vars.Count>0)
                {
                    foreach (GlobalVariable wfVar in run.Vars)
                    {
                        XmlNode varNode = XmlDataUtil.AddElement(ref xDoc, varRootNode, "Variable");
                        XmlDataUtil.UpdateAttribute(ref xDoc, varNode, "VariableName", wfVar.VarName);
                        XmlDataUtil.UpdateAttribute(ref xDoc, varNode, "DataType", ((int) wfVar.DataType).ToString());
                        XmlDataUtil.UpdateAttribute(ref xDoc, varNode, "VariableValue", wfVar.VarValue.ToString());
                    }
                }
                SqlParameter varParam=new SqlParameter("@Vars", xDoc.OuterXml);
                cmd.Parameters.AddRange(new SqlParameter[]
                                            {
                                                runIDparam, workflowIDParam,
                                                triggerInstanceIDParam, 
                                                submitTimeParam, startTimeParam, 
                                                finishTimeParam, varParam
                                            });
                cmd.ExecuteNonQuery();
                scope.Complete();
            }
            catch(Exception ex)
            {
                ExceptionHandler.HandlesException(ex);
            }
            finally
            {
                scope.Dispose();
                conn.Close();
            }
        }

        /// <summary></summary>
        public static Run GetRunByJob(Guid jobID)
        {
            Job job = JobDALC.GetJob(jobID);
            return RunDALC.GetRun(job.RunID);
        }

        /// <summary></summary>
        public static Run GetRun(Guid runID)
        {
            Run run = new Run();
            string connStr = ConfigurationManager.ConnectionStrings["Workflow"].ConnectionString;
            SqlConnection conn = new SqlConnection(connStr);
            try
            {
                conn.Open();
                SqlCommand cmd = conn.CreateCommand();
                cmd.CommandText = "GetRun";
                cmd.CommandType = CommandType.StoredProcedure;
                SqlParameter runIDparam = new SqlParameter("@RunID", runID.ToString());
                cmd.Parameters.Add(runIDparam);
                SqlDataReader reader = cmd.ExecuteReader();
                if(reader.Read())
                {
                    run.RunID=new Guid(reader["RunID"].ToString());
                    run.WorkflowID=new Guid(reader["WorkflowID"].ToString());
                    run.TriggerInstanceID=new Guid(reader["TriggerInstanceID"].ToString());
                    run.SubmitTime = DateTime.Parse(reader["SubmitTime"].ToString());
                    run.StartTime = DateTime.Parse(reader["StartTime"].ToString());
                    run.FinishTime = DateTime.Parse(reader["FinishTime"].ToString());
                    run.Vars = null;
                    string xml = reader["Vars"].ToString();
                    XmlDocument xDoc=new XmlDocument();
                    xDoc.LoadXml(xml);
                    XmlNodeList varNodes = xDoc.SelectNodes("//Variable");
                    if (varNodes != null && varNodes.Count > 0)
                    {
                        run.Vars=new List<GlobalVariable>();
                        foreach (XmlNode varNode in varNodes)
                        {
                            string varName = varNode.Attributes.GetNamedItem("VariableName").Value;
                            SimpleDataType dataType =
                                (SimpleDataType) int.Parse(varNode.Attributes.GetNamedItem("DataType").Value);
                            string varVal = varNode.Attributes.GetNamedItem("VariableValue").Value;
                            run.Vars.Add(new GlobalVariable(varName, dataType, varVal));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                ExceptionHandler.HandlesException(ex);
            }
            finally
            {
                conn.Close();
            }
            return run;
        }

        /// <summary></summary>
        public static List<Run> GetRunByWorkflow(Guid wfID)
        {
            List<Run> runs=new List<Run>();
            
            string connStr = ConfigurationManager.ConnectionStrings["Workflow"].ConnectionString;
            SqlConnection conn = new SqlConnection(connStr);
            try
            {
                conn.Open();
                SqlCommand cmd = conn.CreateCommand();
                cmd.CommandText = "GetRunByWorkflow";
                cmd.CommandType = CommandType.StoredProcedure;
                SqlParameter runIDparam = new SqlParameter("@WorkflowID", wfID.ToString());
                cmd.Parameters.Add(runIDparam);
                SqlDataReader reader = cmd.ExecuteReader();
                while (reader.Read())
                {
                    Run run = new Run();
                    run.RunID = new Guid(reader["RunID"].ToString());
                    run.WorkflowID = new Guid(reader["WorkflowID"].ToString());
                    run.TriggerInstanceID = new Guid(reader["TriggerInstanceID"].ToString());
                    run.SubmitTime = DateTime.Parse(reader["SubmitTime"].ToString());
                    run.StartTime = DateTime.Parse(reader["StartTime"].ToString());
                    run.FinishTime = DateTime.Parse(reader["FinishTime"].ToString());
                    run.Vars = null;
                    string xml = reader["Vars"].ToString();
                    XmlDocument xDoc = new XmlDocument();
                    xDoc.LoadXml(xml);
                    XmlNodeList varNodes = xDoc.SelectNodes("//Variable");
                    if (varNodes != null && varNodes.Count > 0)
                    {
                        run.Vars = new List<GlobalVariable>();
                        foreach (XmlNode varNode in varNodes)
                        {
                            string varName = varNode.Attributes.GetNamedItem("VariableName").Value;
                            SimpleDataType dataType =
                                (SimpleDataType) int.Parse(varNode.Attributes.GetNamedItem("DataType").Value);
                            string varVal = varNode.Attributes.GetNamedItem("VariableValue").Value;
                            run.Vars.Add(new GlobalVariable(varName, dataType, varVal));
                        }
                    }

                    runs.Add(run);
                }
            }
            catch (Exception ex)
            {
                ExceptionHandler.HandlesException(ex);
            }
            finally
            {
                conn.Close();
            }
            return runs;
        }

        /// <summary></summary>
        public static void ClearRunHistory()
        {
            string connStr = ConfigurationManager.ConnectionStrings["Workflow"].ConnectionString;
            SqlConnection conn=new SqlConnection(connStr);
            TransactionScope scope = new TransactionScope();
            try
            {
                conn.Open();
                SqlCommand cmd = conn.CreateCommand();
                cmd.CommandType = CommandType.Text;
                cmd.CommandText = "truncate table Runs";
                cmd.ExecuteNonQuery();
                cmd.CommandText = "truncate table Jobs";
                cmd.ExecuteNonQuery();
                cmd.CommandText = "truncate table JobInstruction";
                cmd.ExecuteNonQuery();
                cmd.CommandText = "truncate table JobOutput";
                cmd.ExecuteNonQuery();
                cmd.CommandText = "truncate table WorkflowTriggerInstance";
                cmd.ExecuteNonQuery();
                scope.Complete();
            }
            catch (Exception ex)
            {
                ExceptionHandler.HandlesException(ex);
            }
            finally
            {
                scope.Dispose();
                conn.Close();
            }
        }
    }
}
